//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
// Data Memory and Special Function Register Interface for M8051W/EW
// 
// $Log: m3s006dy.v,v $
// Revision 1.9  2001/11/20
// First checkin of version 2 features and name change
//
// Revision 1.2  2001/10/31
// First parsable verilog for EW
//
// Revision 1.1.1.1  2001/07/17
// Re-imported E-Warp from Farnham filesystem
//
// Revision 1.8  2000/10/24
// Multiplier rewritten to improve power consumption.
// Code changes for Leonardo (ECN01372).
// Code changes for formal verification tools (ECN01410).
// MOVX @Ri page address controllable from PORT2I if I/O ports ommitted (ECN01387).
//
// Revision 1.7  2000/05/17
// ECN01354: SFRRE qualifiication
//
// Revision 1.6  2000/02/10
// Redundancy reduced for code coverage
//
// Revision 1.5  2000/02/05
// Name change repercussions
//
// Revision 1.4  2000/02/05
// Name change repercussions
//
// Revision 1.3  1999/11/30
// More debug changes.
//
// Revision 1.2  1999/11/18
// SFR read enable added, TRAP and DPTR fixes.
//
// Revision 1.1.1.1  1999/10/28
// "initialization and source check-in for m8051e"
//
// Revision 1.1  1999/10/22
// Initial revision
//
////////////////////////////////////////////////////////////////////////////////

`include "m8051w_defs.v"

`include "m8051w_cfg.v"

module m3s006dy (SOURCE_A, DESTIN_A, SFRSA, INDIRECT_DATA,
//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
                 STACK_POINTER, NDESTIN_WE, NSOURCE_RE, SFR_WRITE,
                 SOURCE_IS_SFR, BIT_ADDRESS, PROGDI, OPCODE, PSW, SOURCE_DI,
                 MEM_CON, CONDITION_MET, REG_RESULT, WRITE_PSW,
                 SFR_WRITE_EN, STATE, LAST_CYC, INTERNAL_WAIT, INTERNAL_RESET,
                 CCLK);

  output [7:0]  SOURCE_A, DESTIN_A;
  output [6:0]  SFRSA;
  output [7:0]  INDIRECT_DATA;
  output [7:0]  STACK_POINTER;
  output        NDESTIN_WE;
  output        NSOURCE_RE;
  output        SFR_WRITE;
  output        SOURCE_IS_SFR;
  output [2:0]  BIT_ADDRESS;

  input  [7:0]  PROGDI;
  input  [2:0]  OPCODE;
  input  [4:3]  PSW;
  input  [7:0]  SOURCE_DI;
  input  [15:0] MEM_CON;
  input         CONDITION_MET;
  input         WRITE_PSW;
  input  [2:0]  STATE;
  input         LAST_CYC;
  input         INTERNAL_WAIT, INTERNAL_RESET;
  input         CCLK;
  input  [7:0]  REG_RESULT;
  input  [3:3]  SFR_WRITE_EN;

  reg [7:0] DESTIN_A;                                 
  reg [7:0] STACK_POINTER;
  reg       L_NDESTIN_WE;                               // data write qualifier
  reg       L_NSOURCE_RE;                               // data read qualifier
  reg       L_SFR_WRITE;
  reg [2:0] BIT_ADDRESS;
  reg [7:0] DIRECT_SRC_ADDR;                            // data address register
  reg       SOURCE_IS_SFR;                              // memory/SFR selector
  reg       SELECT_INDIRECT;
  reg       RAM_BYPASS;                                 // read index internally

  wire [7:0] SOURCE_A;
  wire [7:0] NEXT_DIRECT_SRC_ADDR;                      // Unreg'd read addr
  wire [7:0] INDIRECT_ADDR, REGISTER_ADDR, BIT_OP_ADDR; // derived address forms
  wire [7:0] INDIRECT_DATA;
  wire       DESTIN_IS_SFR;                             // memory/SFR selector
  wire [7:0] NEXT_STACK_PTR;                            // Stack ptr next state
  wire       WRITE_STACK_PTR;                           // Stack ptr write enble
  wire       NEXT_RAM_BYPASS;

 // RAM_BYPASS indicates that the next instruction will read an index register
 // from an internally stored value

  assign NEXT_RAM_BYPASS = ~L_NDESTIN_WE && `CLP2 && (~|DESTIN_A[7:5]         &&
                                                   ~|DESTIN_A[2:1]            &&
                                                   DESTIN_A[4:3] == PSW[4:3]  &&
                                                   DESTIN_A[0] == PROGDI[0]);

  // Generate register address from OPCODE and PSW bits, and 
  // bit operation address from program data.
  // Add NEXT_RAM_BYPASS dependence to avoid simultanoeus read/write at same
  // address

  `ifdef sync_iram
    assign INDIRECT_ADDR = WRITE_PSW?
                           {2'b00, NEXT_RAM_BYPASS, REG_RESULT[4:3],
                            2'b00, PROGDI[0]}:
                           {2'b00, NEXT_RAM_BYPASS, PSW[4:3],
                            2'b00, PROGDI[0]};
  `else
    assign INDIRECT_ADDR = {2'b00, RAM_BYPASS, PSW[4:3], 2'b00, OPCODE[0]};  
  `endif

  assign REGISTER_ADDR = {3'b000, PSW[4:3], OPCODE[2:0]};

  assign INDIRECT_DATA = RAM_BYPASS? DIRECT_SRC_ADDR: SOURCE_DI;

  assign BIT_OP_ADDR[7]   = PROGDI[7];
  assign BIT_OP_ADDR[6:0] = PROGDI[7]? {PROGDI[6:3], 3'b000}:
                                        {3'b010, PROGDI[6:3]};

  // Register direct addresses for source and destination registers.
  // CALLs and RETurns access two data memory bytes.
  // Indirect, register and bit operation addresses are common to both
  // data memory ports.
  // Select between SFR and data memory on basis of addressing mode and
  // address bit 7.

  assign NEXT_DIRECT_SRC_ADDR = ({8{MEM_CON[0]}} & PROGDI)         |
                                ({8{MEM_CON[1]}} & STACK_POINTER)  |
                                ({8{MEM_CON[2]}} & REGISTER_ADDR)  |
                                ({8{MEM_CON[3]}} & INDIRECT_DATA)  |
                                ({8{MEM_CON[4]}} & BIT_OP_ADDR);

  always @(posedge CCLK)
  begin: p_register_addrs
    if (~INTERNAL_WAIT) begin
      if (`CLP2) begin
        SOURCE_IS_SFR   <= 0;
        SELECT_INDIRECT <= 1;
        DIRECT_SRC_ADDR <= REG_RESULT;
      end
      else if (`C1P1 || `C1P2 && MEM_CON[9]) begin
        DIRECT_SRC_ADDR <= NEXT_DIRECT_SRC_ADDR;
        SOURCE_IS_SFR   <= MEM_CON[15] && PROGDI[7] &&
                           (LAST_CYC || MEM_CON[6]);
        BIT_ADDRESS     <= PROGDI[2:0] & {3{MEM_CON[4]}};
        SELECT_INDIRECT <= 0;
      end
      else if (`C1P2) begin
        SOURCE_IS_SFR   <= MEM_CON[15] && DIRECT_SRC_ADDR[7] && ~MEM_CON[6];
      end
  
      if (`C1P1 || `C1P2 && |MEM_CON[13:12])
        DESTIN_A <= ({8{MEM_CON[4]}} & BIT_OP_ADDR)                            |
                    ({8{MEM_CON[5]}} & PROGDI)                                 |
                    ({8{MEM_CON[6]}} & NEXT_STACK_PTR)                         |
                    ({8{MEM_CON[7]}} & REGISTER_ADDR)                          |
                    ({8{MEM_CON[8]}} & INDIRECT_DATA);

    end
  end

  // Source address multiplexer.
  `ifdef sync_iram
    assign SOURCE_A = `CLP2 ? INDIRECT_ADDR: NEXT_DIRECT_SRC_ADDR;
  `else
    assign SOURCE_A = SELECT_INDIRECT? INDIRECT_ADDR: DIRECT_SRC_ADDR;
  `endif

  // During multicycle instructions use registered data address bit 7 after C1P2
  // to determine SFR mode.

  assign DESTIN_IS_SFR = ~|MEM_CON[8:6] && (`C1P1? PROGDI[7]: DESTIN_A[7]);

  // Data Memory and Special Function Register Write Control Logic

  // MEM_CON  |  Memory/SFR write time
  // 10 11 12 |
  // ---------+----------------------------------------
  //  0  0  0 |  No write back using memory interface
  //  1  0  0 |  End of phase 2 of last machine cycle,standard result write time
  //  0  1  0 |  End of phase 2 of first machine cycle, stack operations only
  //  0  0  1 |  End of phase 1 of second machine cycle, call instructions only
  //
  // MEM_CON[14] indicates the JBC instruction
  //
  always @(posedge CCLK)
  begin: p_strobes
    // Define destination write times w.r.t. the state machine.
    if (INTERNAL_RESET) begin
      L_NDESTIN_WE <= 1'b1;
      L_NSOURCE_RE <= 1'b1;
      L_SFR_WRITE  <= 1'b0;
      RAM_BYPASS   <= 1'b0;
    end
    else if (~INTERNAL_WAIT) begin
      L_NDESTIN_WE   <= ~(LAST_CYC && ~STATE[0] && MEM_CON[10] &&
                        (~MEM_CON[14] || CONDITION_MET) ||
                        `C1P1 && MEM_CON[11] || `C1P2 && MEM_CON[12])
                        || DESTIN_IS_SFR; 
      L_SFR_WRITE    <= LAST_CYC && ~STATE[0] && MEM_CON[10] && DESTIN_IS_SFR &&
                        (~MEM_CON[14] || CONDITION_MET);

    `ifdef sync_iram
      L_NSOURCE_RE   <=  ~(`CLP1 || `CLP2 || `C1P1 && MEM_CON[9]);
    `else
      L_NSOURCE_RE   <= NEXT_RAM_BYPASS || `C1P2 && MEM_CON[11] ||
                        `C2P1 && MEM_CON[12];
    `endif

      if `CLP2
        RAM_BYPASS <= NEXT_RAM_BYPASS;   // Disregard next RAM register fetch
      else
        RAM_BYPASS <= 1'b0;
    end
  end

  // The Stack Pointer

  assign WRITE_STACK_PTR = SFR_WRITE_EN[3]                                    ||
                           `C1P1 && (MEM_CON[1] || MEM_CON[6])                ||
                           `C1P2 && (MEM_CON[9] || MEM_CON[12]);

  assign NEXT_STACK_PTR = SFR_WRITE_EN[3]? REG_RESULT:
                                       STACK_POINTER + {{7{MEM_CON[1]}}, 1'b1};

  always @(posedge CCLK)
  begin: p_stack_ptr
    if (INTERNAL_RESET)
      STACK_POINTER <= 8'h07;
    else if (WRITE_STACK_PTR && ~INTERNAL_WAIT)
      STACK_POINTER <= NEXT_STACK_PTR;
  end

  // Export direct source address for SFR read data multiplexers
  assign SFRSA = DIRECT_SRC_ADDR[6:0];

  assign NDESTIN_WE = INTERNAL_WAIT || L_NDESTIN_WE;
  assign NSOURCE_RE = INTERNAL_WAIT || L_NSOURCE_RE;
  assign SFR_WRITE  = ~INTERNAL_WAIT && L_SFR_WRITE;

endmodule
